﻿using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Threading;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;

using PickGold;
using PickGold.Api;
using PickGold.Base;
using PickGold.Collections;

using BaseCommon = PickGold.Base.Common;

namespace PickGold.Base.OCR
{
	[Serializable]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public class ImageModelArea
	{
		private ImageModel _Model;
		private int _Precision;
		private byte _Tolerance;
		private int _Relatively;
		private bool _ContinueOnUnmatch;

		/// <summary>
		/// 模板内容位置（当前模板的指定位置）
		/// </summary>
		public Rectangle Area;

		/// <summary>
		/// 匹配位置（欲匹配的图片的指定位置）
		/// </summary>
		public Rectangle AreaLimit;

		internal ImageModelArea(ImageModel model) : this(model, Rectangle.Empty) { }
		internal ImageModelArea(ImageModel model, int x, int y, int width, int height) : this(model, new Rectangle(x, y, width, height)) { }
		internal ImageModelArea(ImageModel model, Rectangle area)
		{
			this._Model = model;
			if (area == Rectangle.Empty)
				this.Area = new Rectangle(0, 0, model.Model.Width, model.Model.Height);
			else
				this.Area = area;
		}

		/// <summary>
		/// 精度
		/// </summary>
		public int Precision
		{
			set
			{
				this._Precision = value;
			}
			get
			{
				return this._Precision;
			}
		}

		/// <summary>
		/// 容差
		/// </summary>
		public byte Tolerance
		{
			set
			{
				this._Tolerance = value;
			}
			get
			{
				return this._Tolerance;
			}
		}

		/// <summary>
		/// 相对结果集的位置的索引，零或大于等于当前索引：相对于上一个位置，负数为全局位置
		/// </summary>
		public int Relatively
		{
			set
			{
				if (value > 0)
				{
					var index = -1;
					var items = this._Model.GetAllItems();
					for (var i = 0; i < items.Length; i++)
					{
						index = i;
						if (items[i] == this)
							break;

						index = -1;
					}

					if (index >= 0 && value > index)
						throw new ArgumentOutOfRangeException(MethodBase.GetCurrentMethod().Name, string.Format("相对引用索引必须小于当前索引【{0}】值！", index));

					if (items[value - 1]._ContinueOnUnmatch)
						throw new ArgumentOutOfRangeException(MethodBase.GetCurrentMethod().Name, "相对引用的模型不可以忽略错误！");
				}
				this._Relatively = value;
			}
			get
			{
				return this._Relatively;
			}
		}

		/// <summary>
		/// 不匹配时继续续搜索
		/// </summary>
		public bool ContinueOnUnmatch
		{
			set
			{
				if (value)
				{
					var index = -1;
					var items = this._Model.GetAllItems();
					for (var i = 0; i < items.Length; i++)
					{
						index = i;
						if (items[i] == this)
							break;

						index = -1;
					}
					if (index >= 0)
					{
						index++;
						for (var i = 0; i < items.Length; i++)
						{
							if (items[i].Relatively == index)
								throw new ArgumentOutOfRangeException(MethodBase.GetCurrentMethod().Name, string.Format("在当前索引【{0}】有其它模型【{1}】相对引用的情况下不可以忽略错误！", index, i));
						}
					}
				}
				this._ContinueOnUnmatch = value;
			}
			get
			{
				return this._ContinueOnUnmatch;
			}
		}

		public ImageModel ImageModel
		{
			get
			{
				return this._Model;
			}
		}

		#region Rectangle

		public int Left
		{
			get
			{
				return this.Area.Left;
			}
		}

		public int Top
		{
			get
			{
				return this.Area.Top;
			}
		}

		public int Right
		{
			get
			{
				return this.Area.Right;
			}
		}

		public int Bottom
		{
			get
			{
				return this.Area.Bottom;
			}
		}

		public int X
		{
			get
			{
				return this.Area.X;
			}
		}

		public int Y
		{
			get
			{
				return this.Area.Y;
			}
		}

		public int Width
		{
			get
			{
				return this.Area.Width;
			}
		}

		public int Height
		{
			get
			{
				return this.Area.Height;
			}
		}

		#endregion

		public Bitmap GetAreaBitmap()
		{
			var bmp = this._Model.Model.Clone() as Bitmap;
			var bitmap = new Bitmap(bmp, this.Area.Width, this.Area.Height);
			var gps = Graphics.FromImage(bitmap);
			gps.DrawImage(bmp, new Rectangle(0, 0, this.Area.Width, this.Area.Height), this.Area, GraphicsUnit.Pixel);
			gps.Dispose();
			return bitmap;
		}

		public override string ToString()
		{
			var t = string.Format("; Precision:{0}; Tolerance:{1};Relatively:{2};AreaLimit:", this._Precision, this._Tolerance, this._Relatively);
			t = this.Area + t + this.AreaLimit;
			if (this._ContinueOnUnmatch)
				return t + "; ContinueOnUnmatch;";

			return t;
			//return base.ToString();
		}
	}
}
